package plgnet

import (
	"dgo/MyProj/PrjHttpUtils"
	"dgo/goutils/utils"
	"gitee.com/ymofen/gobase"
	"golang.org/x/time/rate"
	"net/http"
	"sync/atomic"
	"time"
)

type PlgCtrlHttpRequestRec struct {
	BlockN      int32
	Id          string
	Uri         string
	LastReqT    time.Time
	ReqMonitor  *utils.MonitorSpeedNTimeRec
	ReqHead     string
	FromAddr    string
	RateLimiter *rate.Limiter
}

func (this *PlgCtrlHttpRequestRec) OnRequest(w http.ResponseWriter, r *http.Request) bool {
	this.ReqMonitor.Delta(1)
	rate := this.RateLimiter
	if rate == nil || rate.Allow() {
		var sb utils.BytesBuilder
		PrjHttpUtils.GetRequestHeader(r.Header, ":", "\n", &sb)
		this.ReqHead = sb.String()
		this.FromAddr = r.RemoteAddr
		this.LastReqT = time.Now()
		return true
	} else {
		http.Error(w, "接口访问过于频繁", 503)
		atomic.AddInt32(&this.BlockN, 1)
		return false
	}

}

func (this *NetHttpPlgCtrl) checkGetReqRec(uri string) *PlgCtrlHttpRequestRec {
	obj := this.reqlst.LoadOrStoreFunc(uri, func() interface{} {
		rval := &PlgCtrlHttpRequestRec{
			Id:         uri,
			Uri:        uri,
			ReqMonitor: utils.NewMonitorSpeedNTimeRec(),
		}
		str := this.ratelimitNPer
		if len(str) > 0 {
			s01, s02 := gobase.Split2Str(str, "/")
			n1, n2 := gobase.StrToIntDef(s01, 0), gobase.StrToIntDef(s02, 0)
			if n1 == 0 {
				rval.RateLimiter = nil
			} else {
				rval.RateLimiter = rate.NewLimiter(rate.Limit(n1), n2)
			}

		}
		utils.Monitor.AddMonitor(rval.ReqMonitor)
		return rval
	}, func(val interface{}) {
		itm := val.(*PlgCtrlHttpRequestRec)
		itm.ReqMonitor = nil
		utils.Monitor.RemoveMonitorRec(itm.ReqMonitor)
	}).(*PlgCtrlHttpRequestRec)
	return obj
}

func (this *NetHttpPlgCtrl) ReleaseStatReqLst() {
	this.reqlst.Range(func(key, value interface{}) bool {
		utils.Monitor.RemoveMonitorRec(value.(*PlgCtrlHttpRequestRec).ReqMonitor)
		return true
	})
}
